package com.github.util;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.github.bean.ServerUser;
import com.github.pojo.WsBaseResult;
import com.github.pojo.WsResult;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.web.socket.WebSocketSession;

import javax.annotation.PreDestroy;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.security.MessageDigest;
import java.util.UUID;
import java.util.concurrent.*;

@Component
public class Utils {
    // 在控制器或服务中添加测试
    private static final Logger logger = LoggerFactory.getLogger(SocketSendThread.class);

    // 优化：改进线程池配置，使用更合理的线程数
    private static final ScheduledExecutorService deviceCheckScheduler = Executors.newScheduledThreadPool(
            Math.max(8, Runtime.getRuntime().availableProcessors() / 4), // 根据CPU核心数动态调整
            r -> {
                Thread t = new Thread(r, "DeviceChecker-" + System.currentTimeMillis());
                t.setDaemon(true); // 设置为守护线程
                return t;
            });

    // 优化：延迟检查线程池
    private static final ExecutorService delayedCheckExecutor = Executors.newFixedThreadPool(
            Math.max(16, Runtime.getRuntime().availableProcessors() / 2), // 根据CPU核心数动态调整
            r -> {
                Thread t = new Thread(r, "DelayedChecker-" + System.currentTimeMillis());
                t.setDaemon(true); // 设置为守护线程
                return t;
            });

    private final static ObjectMapper objectMapper = new ObjectMapper();

    // 优化：通用调度器
    private static final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(
            Math.max(4, Runtime.getRuntime().availableProcessors() / 8), // 根据CPU核心数动态调整
            r -> {
                Thread t = new Thread(r, "GeneralScheduler-" + System.currentTimeMillis());
                t.setDaemon(true); // 设置为守护线程
                return t;
            });

    // 新增：优雅关闭所有线程池
    @PreDestroy
    public void shutdownAllExecutors() {
        logger.info("Shutting down all executors in Utils...");
        shutdownExecutor(deviceCheckScheduler, "DeviceCheckScheduler");
        shutdownExecutor(delayedCheckExecutor, "DelayedCheckExecutor");
        shutdownExecutor(scheduler, "GeneralScheduler");
    }

    // 新增：优雅关闭单个线程池
    private void shutdownExecutor(ExecutorService executor, String name) {
        if (executor != null && !executor.isShutdown()) {
            logger.info("Shutting down {}...", name);
            executor.shutdown();
            try {
                if (!executor.awaitTermination(30, TimeUnit.SECONDS)) {
                    logger.warn("{} did not terminate gracefully, forcing shutdown", name);
                    executor.shutdownNow();
                } else {
                    logger.info("{} terminated gracefully", name);
                }
            } catch (InterruptedException e) {
                logger.warn("{} shutdown interrupted, forcing shutdown", name);
                executor.shutdownNow();
                Thread.currentThread().interrupt();
            }
        }
    }

    // 新增：优雅关闭ScheduledExecutorService
    private void shutdownExecutor(ScheduledExecutorService executor, String name) {
        if (executor != null && !executor.isShutdown()) {
            logger.info("Shutting down {}...", name);
            executor.shutdown();
            try {
                if (!executor.awaitTermination(30, TimeUnit.SECONDS)) {
                    logger.warn("{} did not terminate gracefully, forcing shutdown", name);
                    executor.shutdownNow();
                } else {
                    logger.info("{} terminated gracefully", name);
                }
            } catch (InterruptedException e) {
                logger.warn("{} shutdown interrupted, forcing shutdown", name);
                executor.shutdownNow();
                Thread.currentThread().interrupt();
            }
        }
    }

    public static String getParamValue(String uri, String param) {
        String flag = param + "=";
        if (uri != null && uri.contains(flag)) {
            int index = uri.indexOf(flag);
            String subString = uri.substring(index);
            int endIndex = subString.indexOf("&");
            if (endIndex == -1) {
                return subString.substring(flag.length());
            }
            return subString.substring(flag.length(), endIndex);
        }
        return "";
    }

    public static String encrypt() {
        StringBuilder str = new StringBuilder();
        for (int i = 0; i < 32; i++) {
            str.append((char) ("wTRZr:[dDBsHYDB88SE]{yGHvui\\NjeY".charAt(i) - 3));
        }
        return str.toString();
    }

    // 获取Token
    public static String getToken() {
        try {
            String uuid = UUID.randomUUID().toString().replace("-", "");
            MessageDigest md5 = MessageDigest.getInstance("MD5");
            md5.update(uuid.getBytes());
            byte[] digest = md5.digest();
            StringBuilder sb = new StringBuilder();
            for (byte b : digest) {
                sb.append(String.format("%02x", b));
            }
            return sb.toString();
        } catch (Exception e) {
            return null;
        }
    }

    public static JsonNode toJsonNode(String str) {
        try {
            return objectMapper.readTree(str);
        } catch (Exception e) {
            return null;
        }
    }

    public static void checkDevice(ServerUser serverUser) {

        deviceCheckScheduler.schedule(() -> {
            try {
                if (serverUser.isCardOnline()) {
                    WsResult<?> result = WsResult.deviceOnline(Role.CALL);
                    toServerSendMsg(serverUser, result);
                }
                if (serverUser.isVoiceOnline()) {
                    WsResult<?> result = WsResult.deviceOnline(Role.VOICE);
                    toServerSendMsg(serverUser, result);
                }
            } catch (Exception ignore) {

            }
        }, 500, TimeUnit.MILLISECONDS);
    }

    public static void toSessionSendMsg(WebSocketSession session, WsBaseResult result) throws IOException {
        String json = objectMapper.writeValueAsString(result);
        logger.info("WebSocket ==>toSessionSendMsg-->" + json);
        SocketSendThread.sendMessage(session, json);
        // session.sendMessage(new TextMessage(AESEncrypt.encrypt(json)));
        // logger.info("WebSocket ==> " + json);
    }

    public static void toServerSendMsg(ServerUser serverUser, WsBaseResult result) {
        try {
            String json = objectMapper.writeValueAsString(result);
            if (!serverUser.isServerOnline()) {
                logger.info("WebSocket -> Server ==> Server is offline >>> " + result);
                return;
            }
            SocketSendThread.sendMessage(serverUser.getServerSession(), json);
            // serverUser.getServerSession().sendMessage(new
            // TextMessage(AESEncrypt.encrypt(json)));
            logger.info("WebSocket -> Server ==> " + json);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    public static void toCallSendMsg(ServerUser serverUser, WsBaseResult result) {
        try {
            String json = objectMapper.writeValueAsString(result);
            if (!serverUser.isCardOnline()) {
                logger.info("WebSocket -> Call ==> Call is offline >>> " + result);
                return;
            }
            SocketSendThread.sendMessage(serverUser.getCallSession(), json);
            // serverUser.getCallSession().sendMessage(new
            // TextMessage(AESEncrypt.encrypt(json)));
            logger.info("WebSocket -> Call ==> " + json);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    public static void toVoiceSendMsg(ServerUser serverUser, WsBaseResult result) {
        try {
            String json = objectMapper.writeValueAsString(result);
            if (!serverUser.isVoiceOnline()) {
                logger.info("WebSocket -> Voice ==> Voice is offline >>> " + result);
                return;
            }
            SocketSendThread.sendMessage(serverUser.getVoiceSession(), json);
            // serverUser.getVoiceSession().sendMessage(new
            // TextMessage(AESEncrypt.encrypt(json)));
            logger.info("WebSocket -> Voice ==> " + json);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    public static String getRandomString(int i) {
        String str = "0123456789";
        StringBuilder sb = new StringBuilder();
        for (int j = 0; j < i; j++) {
            int number = (int) (Math.random() * str.length());
            sb.append(str.charAt(number));
        }
        return sb.toString();
    }

    public static void delayedCheck(WebSocketSession session, long time) {
        delayedCheckExecutor.submit(() -> {
            try {
                Thread.sleep(time);
                if (session.isOpen()) {
                    session.close();
                }
            } catch (Exception ignore) {
            }
        });
    }

    /**
     * 获取客户端真实IP（处理代理/负载均衡场景）
     */
    public static String getClientIp(HttpServletRequest request) {
        try {
            // 从代理头获取真实IP
            String ip = request.getHeader("X-Forwarded-For");
            if (isInvalidIp(ip)) {
                ip = request.getHeader("Proxy-Client-IP");
            }
            if (isInvalidIp(ip)) {
                ip = request.getHeader("WL-Proxy-Client-IP");
            }
            if (isInvalidIp(ip)) {
                ip = request.getHeader("HTTP_CLIENT_IP");
            }
            if (isInvalidIp(ip)) {
                ip = request.getHeader("HTTP_X_FORWARDED_FOR");
            }
            // 最终用请求的远程地址
            if (isInvalidIp(ip)) {
                ip = request.getRemoteAddr();
            }
            // 处理多IP（如X-Forwarded-For可能包含多个IP，取第一个）
            if (ip != null && ip.contains(",")) {
                ip = ip.split(",")[0].trim();
            }
            return ip;
        } catch (Exception e) {
            return "";
        }
    }

    /**
     * 判断IP是否无效（null/空/unknown）
     */
    private static boolean isInvalidIp(String ip) {
        return ip == null || ip.isEmpty() || "unknown".equalsIgnoreCase(ip);
    }
}
